﻿using HDFSViewer.Component;
using HDFSViewer.Enum;
using HDFSViewer.Model;
using HDFSViewer.Utility;
using HDFSViewer.View;
using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace HDFSViewer.ViewModel
{
    public class FileDetailControlVM : NotifyObject
    {
        public MainWindowVM MainView { get; set; }

        public HDFSNodeModel Model { get; set; }

        private byte[] _originalData = null;
        private string _content = null;
        public string Content
        {
            get { return _content; }
            set
            {
                _content = value;
                this.RaisePropertyChanged("Content");
            }
        }

        private string _selectedEncoding = "UTF8";
        public string SelectedEncoding
        {
            get { return _selectedEncoding; }
            set
            {
                _selectedEncoding = value;
                this.RaisePropertyChanged("SelectedEncoding");
                if (_selectedEncoding == "HEX")
                {
                    Content = BitConverter.ToString(_originalData);
                }
                else
                {
                    Content = EncodingUtility.ConvertEncoding(_selectedEncoding).GetString(_originalData);
                }
            }
        }

        public FileDetailControlVM(MainWindowVM mainView, HDFSNodeModel model)
        {
            this.Model = model;
            this.MainView = mainView;
            this.LoadData = new DelegateCommand(DoLoadData, DoCanLoadData);
        }

        private string _offset = "0";
        public string Offset
        {
            get { return _offset; }
            set
            {
                _offset = value;
                this.RaisePropertyChanged("Offset");
                this.LoadData.RaiseCanExecuteChanged();
            }
        }

        private string _length = "1000";
        public string Length
        {
            get { return _length; }
            set
            {
                _length = value;
                this.RaisePropertyChanged("Length");
                this.LoadData.RaiseCanExecuteChanged();
            }
        }

        public DelegateCommand LoadData { get; set; }

        private void DoLoadData()
        {
            this.Content = null;
            var log = this.MainView.AddLog(LogType.GetFileContent, LogStatus.Loading, string.Concat("path = ", Model.QueryPath, " Offset = ", Offset, " Length = ", Length), OperationLogModel.Result_Processing);
            if (HDFS.GetInstance().OpenHDFSFile(Model.QueryPath, int.Parse(Offset), int.Parse(Length), ds =>
            {
                try
                {
                    if (ds.Status == TaskStatus.RanToCompletion)
                    {
                        MemoryStream ms = new MemoryStream();
                        ds.Result.Content.CopyToAsync(ms).ContinueWith(cp =>
                        {
                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                _originalData = ms.ToArray();
                                if (_selectedEncoding == "HEX")
                                {
                                    Content = BitConverter.ToString(_originalData);
                                }
                                else
                                {
                                    Content = EncodingUtility.ConvertEncoding(_selectedEncoding).GetString(_originalData);
                                }
                                log.ChangeStatus(LogStatus.Success, OperationLogModel.Result_OK);
                            });
                        });
                    }
                    else
                    {
                        log.ChangeStatusWithDispatcherInvoke(LogStatus.Failed, string.Concat(ds.Status.ToString(), ":", ds.Exception != null && ds.Exception.InnerException != null ? ds.Exception.InnerException.Message : ds.Exception != null ? ds.Exception.Message : "null"));
                    }
                }
                catch (Exception ex)
                {
                    log.ChangeStatusWithDispatcherInvoke(LogStatus.Failed, ex.Message);
                }
            }) == null)
            {
                log.ChangeStatus(LogStatus.Failed, OperationLogModel.Result_Failed);
            }
        }

        private bool DoCanLoadData()
        {
            int offset = 0;
            int length = 0;
            if (int.TryParse(this.Offset, out offset) && int.TryParse(this.Length, out length))
            {
                return offset >= 0 && length > 0;
            }
            return false;
        }
    }
}